#include <stdio.h>
#include "Thread_Pool.h"
#include "stdlib.h"

/**
 *@function: handle the taskqueue's work
  @arg: in fact: Thread_Poolp
  @ret:
*/
void * ThreadPool_Worker(void *arg)
{
  printf("Worker is working!\n");
  //类型转化
  Thread_Poolp poolp = (Thread_Pool *)arg;
  Task task;

  while(1)
  {
    printf("Work A\n");
    //1. 如果队列里面没有任务，那么就保持阻塞？/空闲
    //消费者模型，对应生产者结尾
    pthread_mutex_lock(&poolp->pool_mutex);
    //while(poolp->q_rear == poolp->q_front)
    while((poolp->task_num == 0) && (!poolp->shutdown))
    {
      printf("Worker waiting...\n");
      pthread_cond_wait(&poolp->pool_cond_notemp, &poolp->pool_mutex);
    }

    printf("Work B\n");
    //判断是否终止当前线程
    if(poolp->waitexit_thrd_num > 0) //收到 manager 的waitexit_thrd_num增加信号，终止本信号 
    {
      printf("due to exceed max threads, thread exiting...\n");
      poolp->waitexit_thrd_num --;
      poolp->live_thrd_num --;
      pthread_mutex_unlock(&poolp->pool_mutex);
      pthread_exit(NULL);
    }
//原来的位置
    if(poolp->shutdown == 1)
    {
      poolp->live_thrd_num--;
      pthread_mutex_unlock(&poolp->pool_mutex);
      printf("thread 0x%x is exiting \n", (unsigned int)pthread_self());
      pthread_exit(NULL);
    }

    printf("Work C\n");
    //2. 如果队列里面有任务了，那么开始执行具体的任务
    //2-1:首先取出队首的任务（暂时取出任务，保存在局部变量 Task 中）
    //虽然还没执行该任务，但是其已经保存在局部变量中，因此可以让新的任务进来了
    //*(poolp->tasks[poolp->q_front].func)(poolp->tasks[poolp->q_front].arg);
    task.func =  poolp->tasks[poolp->q_front].func;
    task.arg = poolp->tasks[poolp->q_front].arg;
    //2-2：更新队列的参数
    poolp->q_front = (poolp->q_front+1)%(poolp->max_task);
    poolp->task_num--;
    pthread_cond_signal(&poolp->pool_cond_notfull);//消费者模型，对应生产者开头
    pthread_mutex_unlock(&poolp->pool_mutex);

    //2-3 更新其他参数(busy_thrd_num)
    pthread_mutex_lock(&poolp->busy_mutex);
    poolp->busy_thrd_num++;
    pthread_mutex_unlock(&poolp->busy_mutex);

    //2-4 真正执行任务
    printf("Task starting.....\n");
    (*(task.func))(task.arg);

    //2-5 结束任务执行，释放其参数（假设为堆内存），更新池的参数
    free(task.arg);
    task.arg = NULL;
    printf("Task ending....\n");

    pthread_mutex_lock(&poolp->busy_mutex);
    poolp->busy_thrd_num--;
    pthread_mutex_unlock(&poolp->busy_mutex);
    printf("left tasks:%d\n",poolp->task_num);
  }
  pthread_exit(NULL);//return (void *)0;
}